package com.example.aop;

import com.sun.org.slf4j.internal.Logger;
import com.sun.org.slf4j.internal.LoggerFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.Arrays;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@interface SMSAndMailSender {
    /*短信模板String格式化串*/
    String value() default "";

    String smsContent() default "";

    String mailContent() default "";

    /*是否激活发送功能*/
    boolean isActive() default true;

    /*主题*/
    String subject() default "";
}
//注解实体类

@Aspect
public class AdviceTest {
    @Around("execution(* com.example.aop*(..))")
    public Object process(ProceedingJoinPoint point) throws Throwable {
        System.out.println("@Around：执行目标方法之前...");
        //访问目标方法的参数：
        Object[] args = point.getArgs();
        if (args != null && args.length > 0 && args[0].getClass() == String.class) {
            args[0] = "改变后的参数1";
        }
        //用改变后的参数执行目标方法
        Object returnValue = point.proceed(args);
        System.out.println("@Around：执行目标方法之后...");
        System.out.println("@Around：被织入的目标对象为：" + point.getTarget());
        return "原返回值：" + returnValue + "，这是返回结果的后缀";
    }

    @Before("execution(* com.example.aop*(..))")
    public void permissionCheck(JoinPoint point) {
        System.out.println("@Before：模拟权限检查...");
        System.out.println("@Before：目标方法为：" +
                point.getSignature().getDeclaringTypeName() +
                "." + point.getSignature().getName());
        System.out.println("@Before：参数为：" + Arrays.toString(point.getArgs()));
        System.out.println("@Before：被织入的目标对象为：" + point.getTarget());
    }

    @AfterReturning(pointcut = "execution(* com.example.aop*(..))",
            returning = "returnValue")
    public void log(JoinPoint point, Object returnValue) {
        System.out.println("@AfterReturning：模拟日志记录功能...");
        System.out.println("@AfterReturning：目标方法为：" +
                point.getSignature().getDeclaringTypeName() +
                "." + point.getSignature().getName());
        System.out.println("@AfterReturning：参数为：" +
                Arrays.toString(point.getArgs()));
        System.out.println("@AfterReturning：返回值为：" + returnValue);
        System.out.println("@AfterReturning：被织入的目标对象为：" + point.getTarget());

    }

    @After("execution(* com.example.aop*(..))")
    public void releaseResource(JoinPoint point) {
        System.out.println("@After：模拟释放资源...");
        System.out.println("@After：目标方法为：" +
                point.getSignature().getDeclaringTypeName() +
                "." + point.getSignature().getName());
        System.out.println("@After：参数为：" + Arrays.toString(point.getArgs()));
        System.out.println("@After：被织入的目标对象为：" + point.getTarget());
    }
}

//切面类
@Aspect
@Component("smsAndMailSenderMonitor")
class SMSAndMailSenderMonitor {

    private Logger logger = LoggerFactory.getLogger(SMSAndMailSenderMonitor.class);


    /**
     * 在所有标记了@SMSAndMailSender的方法中切入
     *
     * @param joinPoint
     * @param result
     */
    @AfterReturning(value = "@annotation(com.*.demo.SMSAndMailSender)", returning = "result")//有注解标记的方法，执行该后置返回
    public void afterReturning(JoinPoint joinPoint, Object result) {//注解标注的方法返回值)
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method method = ms.getMethod();
        boolean active = method.getAnnotation(SMSAndMailSender.class).isActive();
        if (!active) {
            return;
        }
        String smsContent = method.getAnnotation(SMSAndMailSender.class).smsContent();
        String mailContent = method.getAnnotation(SMSAndMailSender.class).mailContent();
        String subject = method.getAnnotation(SMSAndMailSender.class).subject();
    }


    /**
     * 在抛出异常时使用
     *
     * @param joinPoint
     * @param ex
     */
    @AfterThrowing(value = "@annotation(com.*.order.monitor.SMSAndMailSender)", throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint, Throwable ex) {//注解标注的方法抛出的异常)
        MethodSignature ms = (MethodSignature) joinPoint.

                getSignature();

        Method method = ms.getMethod();
        String subject = method.getAnnotation(SMSAndMailSender.class).subject();

    }
}

//实体类中使用该注解标注方法
@Service("testService ")
class TestService {
    public static void main(String[] args) {
        System.out.println(many("da"));
    }

    @SMSAndMailSender(smsContent = "MODEL_SUBMIT_SMS", mailContent = "MODEL_SUPPLIER_EMAIL", subject = "MODEL_SUBJECT_EMAIL")
    public static String many(String param) {
        System.out.println(param);
        return "success";
    }
}

